/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package controllers;

import entities.ChangeNotification;
import entities.DeleteNotification;
import entities.Event;
import entities.Invitation;
import entities.Notification;
import entities.OneDayNotification;
import entities.OutdoorEvent;
import entities.ThreeDaysNotification;
import entities.User;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 *
 * @author Alberto, Alessandra
 */
@Stateless
public class NotificationManager {
    
    @PersistenceContext
    EntityManager em;
    
    @EJB
    UserManager um;
    
    @EJB
    InvitationManager im;
    
    @EJB
    CalendarManager cm;
    
    public void createChangeNotifications (Event event) {
        Iterator<Invitation> iter = event.getInvitations().iterator();
        while (iter.hasNext()) {
            User u = iter.next().getUser();
            ChangeNotification not = new ChangeNotification(event, u);
            u.addNotification(not);
            event.addChangeNotification(not);
            em.persist(not);
            em.merge(event);
        }
    }
    
    public void createDeleteNotifications (Event event) {
        Iterator<Invitation> iter = event.getInvitations().iterator();
        while (iter.hasNext()) {
            User u = iter.next().getUser();
            DeleteNotification not = new DeleteNotification(event, u);
            u.addNotification(not);
            event.addDeleteNotification(not);
            em.persist(not);
            em.merge(event);
        }
    }
    
    public void createOneDayNotifications (OutdoorEvent event) {
        deleteOneDayNotifications(event);
        Iterator<User> iter = event.getParticipants().iterator();
        while (iter.hasNext()) {
            User u = iter.next();
            OneDayNotification not = new OneDayNotification(event, u);
            //u.addNotification(not);
            event.addOneDayNotification(not);
            em.persist(not);
            em.merge(event);
            em.merge(u);
        }
    }
    
    public void createThreeDaysNotification (OutdoorEvent event, Date date) {
        deleteThreeDaysNotifications(event);
        User u = event.getCreator();
        ThreeDaysNotification not  = new ThreeDaysNotification(date, event, u);
        event.addThreeDaysNotification(not);
        em.persist(not);
        em.merge(event);
        em.merge(u);
    }
    
    public void deleteChangeNotifications (Event event) {
        ArrayList<ChangeNotification> notifications = new ArrayList<>();
        notifications.addAll(em.createNamedQuery("findChangeNotificationsByEvent", ChangeNotification.class)
            .setParameter("CNevent", event)
            .getResultList());
        Iterator<ChangeNotification> iter = notifications.iterator();
        while (iter.hasNext()) {
            ChangeNotification cn = iter.next();
            event.removeChangeNotification(cn);
            cn.getUser().removeNotification(cn);
            em.remove(cn);
        }
    }
    
    public void deleteDeleteNotification (DeleteNotification notification) {
        notification.getUser().removeNotification(notification);
        notification.getEvent().removeDeleteNotification(notification);
        DeleteNotification not = em.find(DeleteNotification.class, notification.getId());
        em.remove(not);
    }
    
    public void deleteOneDayNotifications (OutdoorEvent event) {
        ArrayList<OneDayNotification> notifications = new ArrayList<>();
        notifications.addAll(em.createNamedQuery("findOneDayNotificationsByEvent", OneDayNotification.class)
            .setParameter("ODNevent", event)
            .getResultList());
        Iterator<OneDayNotification> iter = notifications.iterator();
        while (iter.hasNext()) {
            OneDayNotification odn = iter.next();
            event.removeOneDayNotification(odn);
            odn.getUser().removeNotification(odn);
            em.remove(odn);
        }
    }
    
    public void deleteThreeDaysNotifications (OutdoorEvent event) {
        ArrayList<ThreeDaysNotification> notifications = new ArrayList<>();
        notifications.addAll(em.createNamedQuery("findThreeDaysNotificationsByEvent", ThreeDaysNotification.class)
            .setParameter("TDNevent", event)
            .getResultList());
        Iterator<ThreeDaysNotification> iter = notifications.iterator();
        while (iter.hasNext()) {
            ThreeDaysNotification tdn = iter.next();
            event.removeThreeDaysNotification(tdn);
            tdn.getUser().removeNotification(tdn);
            em.remove(tdn);
        }
    }
    
    public ArrayList<Notification> getNewNotifications () {
        ArrayList<Notification> newnot = new ArrayList<>();
        newnot.addAll(em.createNamedQuery("findByUserNewNot" , Notification.class)
            .setParameter("Nuser", um.getLoggedUser())
            .getResultList());
        return newnot;
    }
    
    public ArrayList<Notification> getNotifications () {
        ArrayList<Notification> not = new ArrayList<>();
        not.addAll(em.createNamedQuery("findByUserNot" , Notification.class)
            .setParameter("Nuser", um.getLoggedUser())
            .getResultList());
        return not;
    }
    
    public void visualize (Notification notification) {
        notification.setVisualized(Boolean.TRUE);
        em.merge(notification);
    }
    
    public void participateInvitationAfterchange (ChangeNotification notification) {
        Iterator<Invitation> iter = notification.getUser().getInvitations().iterator();
        while (iter.hasNext()) {
            Invitation inv = iter.next();
            if (inv.getEvent().equals(notification.getEvent())) {
                inv.setVisualized(Boolean.TRUE);
                im.accept(inv);
            }
        }
    }
    
    public void declineInvitationAfterchange (ChangeNotification notification) {
        Iterator<Invitation> iter = notification.getUser().getInvitations().iterator();
        while (iter.hasNext()) {
            Invitation inv = iter.next();
            if (inv.getEvent().equals(notification.getEvent())) {
                im.decline(inv);
            }
        }
    }
    
    public void rescheduleEvent (ThreeDaysNotification notification) {
        notification.getEvent().setDate(notification.getProposeddate());
        cm.modifyEvent(notification.getEvent());
    }
    
}
